package com.zhang.web.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhang.domain.Category;
import com.zhang.domain.PlayInfo;
import com.zhang.domain.ResultInfo;
import com.zhang.domain.User;
import com.zhang.service.CategoryService;
import com.zhang.service.PlayInfoService;
import com.zhang.service.impl.CategoryServiceImpl;
import com.zhang.service.impl.PlayInfoServiceImpl;
import com.zhang.service.impl.UserServiceImpl;
import com.zhang.util.CookieUtil;
import org.apache.commons.beanutils.BeanUtils;

import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;
import java.util.Random;

@WebServlet("/communication/*")
public class Communication extends BaseServlet {
    private CategoryService categoryService = new CategoryServiceImpl();
    private PlayInfoService playInfoService = new PlayInfoServiceImpl();
    private UserServiceImpl userService = new UserServiceImpl();


    //获取用户名
    public void getUsername(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ResultInfo info = new ResultInfo();

        User user = (User) req.getSession().getAttribute("user");
        if (user != null) {
            info.setFlag(true);
            info.setData(user);
        }


        ObjectMapper mapper = new ObjectMapper();
        resp.setContentType("application/json;charset=utf-8");
        mapper.writeValue(resp.getOutputStream(),info);

    }

    //获取分类数据 (redis)
    public void getCategory(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ResultInfo info = new ResultInfo();
        List<Category> all = categoryService.getAll();
        if (all != null && all.size() > 0) {
            info.setFlag(true);
            info.setData(all);
        }

        writeValue(info, resp);
    }

    //模拟注册
    public void regist1(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        System.out.println("注册成功: " + username + " : " + password);
    }


    //录入玩家信息
    public void enterInfo(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ResultInfo info = new ResultInfo();
        //1.获取参数
        Map<String, String[]> map = req.getParameterMap();
        PlayInfo playInfo = new PlayInfo();
        try {
            BeanUtils.populate(playInfo, map);//将参数封装到playInfo中
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        //判断是否已经录入过
        User user = (User) req.getSession().getAttribute("user");
        PlayInfo playInfo1 = playInfoService.getPlayInfoByUid(user.getUid());
        if(playInfo1 != null ){
            //已经录入过 ->进行修改
            playInfo.setUid(playInfo1.getUid());
            int row = playInfoService.updatePlayInfo(playInfo);
            if (row != 0) {
                info.setFlag(true);
            }
        }else {
            //未录入过 ->进入录入
            int row = playInfoService.enterPlayInfo(playInfo);
            if (row != 0) {
                info.setFlag(true);
            }
        }

        writeValue(info, resp);
    }


    //展示玩家信息 (redis)
    public void showInfo(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /*若后端采用了请求转发 , 前端的通信方式就该用同步通信*/

        //1.获取user对象
        User user = (User) req.getSession().getAttribute("user");
        //已经登录
        //获取玩家信息
        PlayInfo playInfo = playInfoService.getPlayInfoByUid(user.getUid());
        if (playInfo != null) {
            //将数据保存到req域中
            req.setAttribute("playInfo", playInfo);
            //请求转发到 展示玩家数据页
            req.getRequestDispatcher("/showPlayInfo.jsp").forward(req, resp);//b.jsp页面在服务器渲染好后 , 再返回给浏览器

        } else {
            req.setAttribute("enterInfoMsg","请求先录入玩家数据!");
            //请求转发到录入玩家信息界面
            req.getRequestDispatcher("/enterPlayInfo.jsp").forward(req, resp);
        }



    }

    //登录
    public void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取参数
        String username = req.getParameter("username1");
        String password = req.getParameter("password");
        String checkCode = req.getParameter("checkCode");
        String remember = req.getParameter("remember");

        HttpSession session = req.getSession();
        String checkcodeSession = (String) session.getAttribute("CHECKCODE_SERVER");
        session.removeAttribute("CHECKCODE_SERVER");

        User user1 = (User) session.getAttribute("user");
        if (user1 != null) {
            resp.sendRedirect(req.getContextPath() + "/showPlayInfo.jsp");
            return;
        }

        //2.判断验证码
        if (checkCode != null && !"".equals(checkCode) && checkCode.equalsIgnoreCase(checkcodeSession)) {
            //正确
            //3.判断用户名密码
            User user = userService.findUsernameAndPassword(username, password);
            if (user != null) {
                //保存user对象到session域中
                session.setAttribute("user", user);//默认存在30分钟
                //保存用户名密码到cookie中
                if (remember != null && remember.equals("remember-me")) {
                    //点击了记住
                    CookieUtil.addCookie("remember", 7 * 24 * 60 * 60, req, resp, username, password);
                }


                //(请求重定向)用户名密码正确 , 请求重定向到showPlayInfo.jsp(展示玩家数据页)
                resp.sendRedirect(req.getContextPath() + "/showPlayInfo.jsp");
                return;
            } else {
                //(请求转发)用户名密码错误 , 请求转发到communication.jsp , 并作出提示
                req.setAttribute("msg", "用户名或密码错误.");
                req.getRequestDispatcher("/login.jsp").forward(req, resp);
            }

        } else {
            //错误
            req.setAttribute("msg", "验证码错误!!!");
            //请求转发到登录页面
            req.getRequestDispatcher("/login.jsp").forward(req, resp);
        }

    }

    //退出(清除session+cookie)
    public void loginOut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //清除session
        req.getSession().removeAttribute("user");

        //清除cookie
        Cookie cookie = CookieUtil.getCookieByName(req, "remember");
        if (cookie != null) {
            //设置cookie有效时间为0 , 立刻失效
            cookie.setMaxAge(0);
            //设置cookie作用范围
            cookie.setPath(req.getContextPath());
            //响应会浏览器
            resp.addCookie(cookie);

        }


        //请求重定向到登录页
        resp.sendRedirect(req.getContextPath() + "/login.jsp");

    }





    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[请求转发 + 请求重定向]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    //请求转发
    public void forward(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getRequestDispatcher("/login.jsp").forward(req,resp);
    }
    //请求重定向
    public void redirect(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect(req.getContextPath()+"/login.jsp");

    }




    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[cookie&session通信]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~





    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[域通信 jsp特有通信方式]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public void fieldTest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //HttpServlet中没有"pageContext域对象"

        //HttpServletRequest域对象
        req.setAttribute("reqServlet","reqV");
        req.getRequestDispatcher("/communication.jsp").forward(req,resp);//如果在这里进行的请求转发 , 那么本次转发过去后jsp页面就没法获取session+application域中的数据 (因为我在这里就跑路了!)


        //HttpSession域对象
        HttpSession session = req.getSession();
        session.setAttribute("sessionServlet","sessionV");


        //ServletContext域对象
        ServletContext application = req.getServletContext();
        application.setAttribute("applicationServlet","applicationV");



/*        //HttpServletRequest域对象
        req.setAttribute("reqServlet","reqV");
        req.getRequestDispatcher("/communication.jsp").forward(req,resp); //如果是在这里进行的请求转发 , 那么本次转发过去后jsp页面可以获取session+application域中的数据
*/

    }





    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~[获取+响应数据]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    //----------------------获取----------------------:
    public void reqParameter(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, InvocationTargetException, IllegalAccessException {
        //1.获取get请求行参数~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        String queryString = req.getQueryString();
        System.out.println("获取get请求行参数:"+queryString);//username=zhangfei&password=123

        //2.获取post请求体参数~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //(1)获取字符输入流 (注意: 过去字节流和字符串要二选一执行,否则报错!)
        BufferedReader reader = req.getReader();
        String str = null;
        while ((str = reader.readLine()) != null){
            System.out.println("获取post请求体参数:"+str);
        }

        //(2)获取字节输入流
        ServletInputStream inputStream = req.getInputStream();
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = inputStream.read(bytes))!= -1){
            String s = new String(bytes,0,len);
            System.out.println("获取字节输入流:"+s);
        }


        //3.获取请求参数通用方式 (get/post通用)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //(1)getParameter()
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("用户名: "+username);
        System.out.println("密码: "+password);


        //(2)getParameterMap()
        Map<String, String[]> map = req.getParameterMap();
        User user = new User();
        BeanUtils.populate(user,map);
        System.out.println(user);

    }


    //----------------------响应----------------------:

    //1.json
    public void respJSON(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        ResultInfo info = new ResultInfo();
        info.setFlag(true);
        info.setData("数据");
        info.setErrorMsg("错误提示!");

        ObjectMapper mapper = new ObjectMapper();
        resp.setContentType("application/json;charset=utf-8");
        mapper.writeValue(resp.getOutputStream(),info);
    }
    //2.页面
    public void respPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setContentType("text/html;charset=utf-8");
        PrintWriter pw = resp.getWriter();

        pw.write("<h6>页面</h6>");
        pw.write("账号: <input type=\"text\" > ");


    }
    //3.图片
    public void respImage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //服务器通知浏览器不要缓存
        resp.setHeader("pragma","no-cache");
        resp.setHeader("cache-control","no-cache");
        resp.setHeader("expires","0");


        //1.画背景 (在内存中创建一个长80，宽30的图片，默认黑色背景)
        //参数一：长
        //参数二：宽
        //参数三：颜色
        int width = 80;
        int height = 30;
        BufferedImage image = new BufferedImage(width,height, BufferedImage.TYPE_INT_RGB);


        //2.画图获取画笔
        Graphics g = image.getGraphics();
        //设置画笔颜色为灰色
        g.setColor(Color.GRAY);
        //填充图片
        g.fillRect(0,0, width,height);

        //产生4个随机验证码，12Ey
        String checkCode =getCheckCode() ; //1


        //设置画笔颜色为黄色
        g.setColor(Color.YELLOW);
        //设置字体的小大
        g.setFont(new Font("黑体", Font.BOLD,24));
        //向图片上写入验证码
        g.drawString(checkCode,15,25);



        //将内存中的图片输出到浏览器
        //参数一：图片对象
        //参数二：图片的格式，如PNG,JPG,GIF
        //参数三：图片输出到哪里去
        ImageIO.write(image,"PNG",resp.getOutputStream());//3

    }
    private String getCheckCode() {
        String base = "0123456789ABCDEFGabcdefg";
        int size = base.length();
        Random r = new Random();
        StringBuffer sb = new StringBuffer();
        for(int i=1;i<=4;i++){
            //产生0到size-1的随机值
            int index = r.nextInt(size);
            //在base字符串中获取下标为index的字符
            char c = base.charAt(index);
            //将c放入到StringBuffer中去
            sb.append(c);
        }
        return sb.toString();
    }






    public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);


    }


}


























